const {PACKAGE_PATHS} = require ('./configuration');
const path = require ('path');
const fs = require ('fs').promises;
const {exec} = require ('child_process');
const _ = require ('lodash');

const readPackageJson = async index => {
  try {
    const partialPath = PACKAGE_PATHS[index];
    const contents = await fs.readFile (path.join (partialPath));
    return JSON.parse (contents.toString ());
  } catch (error) {}
};

const clear = () => console.clear ();

const execListen = data => {
  return new Promise ((resolve, reject) => {
    let command = data;
    if (data instanceof Array) {
      command = _.join (data, ' ');
    }
    const child = exec (
      command,
      {maxBuffer: 1024 * 1024 * 1024},
      (error, stdout) => {
        if (error) {
          reject (error);
          return;
        }
        resolve (stdout);
      }
    );
    child.stdout.on ('data', data => console.log (data));
  });
};

const mkdirsRecursion = async (dirname, callback) => {
  let err = await fs.access (dirname);
  if (err) {
    await mkdirsRecursion (path.dirname (dirname), async () => {
      await fs.mkdir (dirname);
      if (callback) {
        await callback ();
      }
    });
  } else {
    if (callback) {
      await callback ();
    }
  }
};

const writeFile = async (dirname, content) => {
  try {
    await mkdirsRecursion (path.join (dirname, '../'));
    await fs.writeFile (dirname, content);
  } catch (error) {
    console.log (error);
  }
};

const createStartBat = async () => {
  const runPath = path.join (__dirname, '../../');
  const driveLetter = String (runPath[0]).toLowerCase ();
  const outputFilePath = path.join (runPath, 'start.bat');
  const template = `@echo off\ncd /${driveLetter} ${runPath}\necho "${runPath}"\ncall yarn start\npause`;
  await writeFile (outputFilePath, template, true);
};

function logBright (loggable) {
  console.log (`\x1b[1m${loggable}\x1b[0m`);
}

const updateElectronPkg = async (data, dist, output) => {
  // 启动地址获取绝对地址
  const runPath = path.resolve (PACKAGE_PATHS[0], '../');
  const electronPath = path.resolve (PACKAGE_PATHS[3], '../');
  const distPath = path.join (runPath, dist);
  const distFilePath = path.join (distPath, './server/main.js');
  const mainFilePath = path
    .relative (electronPath, distFilePath)
    .replaceAll ('\\', '/');
  _.set (data, 'main', mainFilePath);
  const electronPathRelative = path.relative (electronPath, distPath);
  const matchPath = path
    .join (electronPathRelative, './**/*')
    .replaceAll ('\\', '/');
  let files = _.get (data, 'build.files');
  _.set (data, 'build.files', _.uniq ([matchPath].concat (files)));
  if (typeof output === 'string') {
    const outputPath = path.join (runPath, output);
    _.set (
      data,
      'build.directories.output',
      path.relative (electronPath, outputPath).replaceAll ('\\', '/')
    );
  }
  await writeFile (
    path.join (runPath, PACKAGE_PATHS[3]),
    JSON.stringify (data, null, 2)
  );
};

const updateElectronTsPkg = async (data, outDir) => {
  const runPath = path.join (__dirname, '../../');
  const electronTsPath = path.join (PACKAGE_PATHS[2], '../');
  const outputPath = path.join (runPath, outDir);
  const mainPath = path
    .join (path.relative (electronTsPath, outputPath), './server')
    .replaceAll ('\\', '/');
  console.log ('electronTsPath', mainPath);
  data['compilerOptions']['outDir'] = mainPath;
  await writeFile (
    path.join (runPath, PACKAGE_PATHS[2]),
    JSON.stringify (data, null, 2)
  );
};

module.exports = {
  readPackageJson,
  clear,
  execListen,
  createStartBat,
  updateElectronPkg,
  updateElectronTsPkg,
  logBright,
  writeFile,
};
